﻿+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                        驱动/硬盘/硬盘.c
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
/* This file contains the device dependent part of a driver for the IBM-AT
* winchester controller. Written by Adri Koppes.
* 温彻斯特，在英国内
* “AT”是英文“先进技术”（Advanced Technology）的缩写
*
*
*
*
* The file contains one entry point:
*
* at_winchester_task: main entry when system is brought up
*                     系统升级时的主要入口
*
* Changes:
* Aug 19, 2005 ata pci support, supports SATA (Ben Gras)
* Nov 18, 2004 moved AT disk driver to user-space (Jorrit N. Herder)
* Aug 20, 2004 watchdogs replaced by sync alarms (Jorrit N. Herder)
* Mar 23, 2000 added ATAPI CDROM support (Michael Temari)
* May 14, 2000 d-d/i rewrite (Kees J. Bot)
* Apr 13, 1992 device dependent/independent split (Kees J. Bot)
* 
*  8月19日，2005 ata pci支持，支持SATA
* 11月18日，2004 将AT磁盘驱动器移动到用户空间
*  8月20日，2004 看门狗由同步报警取代
*  3月23日，2000 添加了ATAPI CDROM支持
*  5月14日，2000 d-d / i重写
*  4月13日，1992 设备依赖/独立分裂
*/

#include "at_wini.h"
#include "../libpci/pci.h"

#include <minix/sysutil.h>
#include <minix/keymap.h>
#include <sys/ioc_disk.h>

#define ATAPI_DEBUG   0       // 硬盘API_调试

/* 读出 和 写入 寄存器 */
#define REG_CMD_BASE0 0x1F0   // register_command_base1
#define REG_CMD_BASE1 0x170   // register_command_base0
#define REG_CTL_BASE0 0x3F6   // register_control_base0
#define REG_CTL_BASE1 0x376   // register_control_base0

#define REG_DATA    0    // register_data
#define REG_PRECOMP 1    // reg_precompensation 预补偿
#define REG_COUNT   2    // reg_count 计数
#define REG_SECTOR  3    // reg_sector 部门
#define REG_CYL_LO  4    // reg_cylinder_low  圆柱
#define REG_CYL_HI  5    // reg_cylinder_high
#define REG_LDH     6    // reg_逻辑区块地址(Logical Block Address, LBA)+drive+head 

#define LDH_DEFAULT 0xA0 // LDH_default ECC是“Error Correcting Code”的简写
#define LDH_LBA          // LDH_逻辑区块地址
#define ldh_init(drive) (LDH_DEFAULT | ((drive) << 4))

/* 只读寄存器 */
#define REG_STATUS    7     /* reg_status */
#define STATUS_BSY    0x80  /* status_busy 忙 */
#define STATUS_RDY    0x40  /* 状态_ready */
#define STATUS_WF     0x20  /* 状态_write fault */
#define STATUS_SC     0x10  /* 状态_seek 寻求 complete (obsolete) */
#define STATUS_DRQ    0x08  /* 状态_data transfer request */
#define STATUS_CRD    0x04  /* 状态_corrected 纠正 data */
#define STATUS_IDX    0x02  /* 状态_index pulse 索引脉冲 */
#define STATUS_ERR    0x01  /* 状态_error */
#define STATUS_ADMBSY 0x100 /* 状态_administratively busy (software) */
#define REG_ERROR     1     /* 寄存器_error code */
#define ERROR_BB      0x80  /* 错误_bad block 坏块 */
#define ERROR_ECC     0x40  /* 错误_bad ecc bytes */
                            /*      ECC是“Error Correcting Code”的简写，中文名称是“错误检查和纠正” */
#define ERROR_ID      0x10  /* 错误_id not found */
#define ERROR_AC      0x04  /* 错误_aborted command */
#define ERROR_TK      0x02  /* 错误_track zero error */
#define ERROR_DM      0x01  /* 错误_no data address mark */

/* 只写寄存器 */
#define REG_COMMAND     7     /* 寄存器_command */
#define CMD_IDLE        0x00  /* 命令_for w_command: drive idle 驱动空闲 */
#define CMD_RECALIBRATE 0x10  /* 命令_recalibrate drive 重新校准驱动器 */
#define CMD_READ        0x20  /* 命令_read data */
#define CMD_READ_EXT    0x24  /* 命令_read data (LBA48 addressed) */
#define CMD_WRITE       0x30  /* 命令_write data */
#define CMD_WRITE_EXT   0x34  /* 命令_write data (LBA48 addressed) */
#define CMD_READVERIFY  0x40  /* 命令_read verify 读入验证 */
#define CMD_FORMAT      0x50  /* 命令_format track 格式轨道 */
#define CMD_SEEK        0x70  /* 命令_seek cylinder */
#define CMD_DIAG        0x90  /* 命令_execute device diagnostics 执行设备诊断 */
#define CMD_SPECIFY     0x91  /* 命令_specify parameters 指定参数 */
#define ATA_IDENTIFY    0xEC  /* identify drive */

/* #define REG_CTL 0x206 */   /* control register */
#define REG_CTL         0     /* 寄存器_control register */
#define CTL_NORETRY     0x80  /* 控制_disable access retry 禁用访问重试 */
#define CTL_NOECC       0x40  /* 控制_disable ecc retry 禁用ecc重试 */
#define CTL_EIGHTHEADS  0x08  /* 控制_more than eight heads */
#define CTL_RESET       0x04  /* 控制_reset controller */
#define CTL_INTDISABLE  0x02  /* 控制_disable interrupts */

#define REG_STATUS      7     /* 寄存器_status */
#define STATUS_BSY      0x80  /* 状态_controller busy */
#define STATUS_DRDY     0x40  /* 状态_drive ready */
#define STATUS_DMADF    0x20  /* 状态_dma ready/drive fault 准备/驱动器故障 */
                              /*      直接存储器访问（Direct Memory Access，DMA） */
#define STATUS_SRVCDSC  0x10  /* 状态_service or dsc */
                              /*      Desired State Configuration (DSC) */
#define STATUS_DRQ      0x08  /* 状态_data transfer request */
#define STATUS_CORR     0x04  /* 状态_correctable error occurred 发生可纠正错误 */
#define STATUS_CHECK    0x01  /* 状态_check error 检查错误 */

/* 中断请求线 */
#define NO_IRQ 0 /* no IRQ set yet */

#define ATAPI_PACKETSIZE 12
#define SENSE_PACKETSIZE 18

/* Common command block 通用命令块 */
struct command {
    u8_t precomp; /* REG_PRECOMP, etc. */
    u8_t count;
    u8_t sector;
    u8_t cyl_lo;
    u8_t cyl_hi;
    u8_t ldh;
    u8_t command;
};

/* 错误代码 */
#define ERR (-1) /* general error */
#define ERR_BAD_SECTOR (-2) /* block marked bad detected 块标记不良检测 */

/* Some controllers don’t interrupt, the clock will wake us up. */
/* 有些控制器不会中断，时钟会唤醒我们 */
#define WAKEUP (32*HZ) /* drive may be out for 31 seconds max */
                       /* 驱动器最大可能熄灭31秒 */

/* Miscellaneous 杂. */
#define MAX_DRIVES          8
#define COMPAT_DRIVES       4
#define MAX_SECS          256 /* controller can transfer this many sectors 控制器可以传输这么多部门 */
#define MAX_ERRORS          4 /* how often to try rd/wt before quitting 戒烟前多久尝试rd / wt */
#define NR_MINORS (MAX_DRIVES * DEV_PER_DRIVE)
#define SUB_PER_DRIVE (NR_PARTITIONS * NR_PARTITIONS)
#define NR_SUBDEVS (MAX_DRIVES * SUB_PER_DRIVE)
#define DELAY_USECS      1000 /* controller timeout in microseconds 微秒 */
#define DELAY_TICKS         1 /* controller timeout in ticks */
#define DEF_TIMEOUT_TICKS 300 /* controller timeout in ticks 控制器超时时间 */
#define RECOVERY_USECS      5 /* controller recovery time in microseconds 控制器恢复时间（以微秒为单位） */
#define RECOVERY_TICKS     30 /* controller recovery time in ticks 控制器恢复时间在滴答 */
#define INITIALIZED      0x01 /* drive is initialized 驱动被初始化 */
#define DEAF             0x02 /* controller must be reset 控制器必须复位 */
#define SMART            0x04 /* drive supports ATA commands 驱动程序支持 ATA 命令 */
#define ATAPI               0 /* don’t bother with ATAPI; optimise out 不要打扰ATAPI;优化出来 */
#define IDENTIFIED       0x10 /* w_identify done successfully 标识完成成功 */
#define IGNORING         0x20 /* w_identify failed once 标识失败一次 */

/* 超时和最大重试的次数 retries重试  */
int timeout_ticks = DEF_TIMEOUT_TICKS, max_errors = MAX_ERRORS;
int wakeup_ticks = WAKEUP;
long w_standard_timeouts = 0, w_pci_debug = 0, w_instance = 0,
w_lba48 = 0, atapi_debug = 0;

int w_testing = 0, w_silent = 0;

int w_next_drive = 0;

/* 变量 */

/* wini is indexed by controller first, then drive (0-3). wini由控制器首先索引，然后驱动
* controller 0 is always the ’compatability’ ide controller, at
* the fixed locations, whether present or not.
*
* 控制器0始终是“兼容性”控制器，在固定位置，无论是否存在。
*
*/
PRIVATE struct wini {      /* main drive struct, one entry per drive 主驱动器结构，每个驱动器一个条目 */
    unsigned state;        /* drive state: deaf, initialized, dead 驱动状态：聋，初始化，死 */
    unsigned w_status;     /* device status register 设备状态寄存器 */
    unsigned base_cmd;     /* command base register 命令基址寄存器*/
    unsigned base_ctl;     /* control base register 控制基址寄存器 */
    unsigned irq;          /* interrupt request line 中断请求线 */
    unsigned irq_mask;     /* 1 << irq */
    unsigned irq_need_ack; /* irq needs to be acknowledged 中断请求需要被承认 */
    int irq_hook_id;       /* id of irq hook at the kernel 内核上的中断请求hook的ID */
    int lba48;             /* supports lba48 支持逻辑区块地址48 */
    unsigned lcylinders;   /* logical number of cylinders (BIOS) 逻辑数字of圆柱 */
    unsigned lheads;       /* logical number of heads 逻辑数字of头 */
    unsigned lsectors;     /* logical number of sectors per track 逻辑数字of扇区每个轨道  */
    unsigned pcylinders;   /* physical number of cylinders (translated) 物理数字of圆柱（翻译） */
    unsigned pheads;       /* physical number of heads 物理数字of头 */
    unsigned psectors;     /* physical number of sectors per track 每个轨道的物理扇区数 */
    unsigned ldhpref;      /* top four bytes of the LDH (head) register LDH（头）寄存器的前四个字节 */
    unsigned precomp;      /* write precompensation cylinder / 4 写预补偿 圆柱面/ 4 */
    unsigned max_count;    /* max request for this drive 对此驱动器的最大请求 */
    unsigned open_ct;      /* in-use count 使用计数 */
    struct device part[DEV_PER_DRIVE];    /* disks and partitions 硬盘和分区 */
    struct device subpart[SUB_PER_DRIVE]; /* subpartitions 子分区 */
} wini[MAX_DRIVES], *w_wn;

PRIVATE int w_device = -1;
PRIVATE int w_controller = -1;
PRIVATE int w_major = -1;
PRIVATE char w_id_string[40];

PRIVATE int win_tasknr;      /* my task number 我的任务号码 */
PRIVATE int w_command;       /* current command in execution 当前命令执行 */
PRIVATE u8_t w_byteval;      /* used for SYS_IRQCTL 用于SYS_中断请求Interrupt Request */
PRIVATE int w_drive;         /* selected drive      选择驱动器 */
PRIVATE int w_controller;    /* selected controller 选择控制器 */
PRIVATE struct device *w_dv; /* device’s base and size 设备基址和大小 */

FORWARD _PROTOTYPE( void init_params, (void) );
FORWARD _PROTOTYPE( void init_drive, (struct wini *, int, int, int, int, int, int));
FORWARD _PROTOTYPE( void init_params_pci, (int) );
FORWARD _PROTOTYPE( int w_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( struct device *w_prepare, (int dev) );
FORWARD _PROTOTYPE( int w_identify, (void) );
FORWARD _PROTOTYPE( char *w_name, (void) );
FORWARD _PROTOTYPE( int w_specify, (void) );
FORWARD _PROTOTYPE( int w_io_test, (void) );
FORWARD _PROTOTYPE( int w_transfer, (int proc_nr, int opcode, off_t position,
iovec_t *iov, unsigned nr_req) );
FORWARD _PROTOTYPE( int com_out, (struct command *cmd) );
FORWARD _PROTOTYPE( void w_need_reset, (void) );
FORWARD _PROTOTYPE( void ack_irqs, (unsigned int) );
FORWARD _PROTOTYPE( int w_do_close, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_other, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int w_hw_int, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int com_simple, (struct command *cmd) );
FORWARD _PROTOTYPE( void w_timeout, (void) );
FORWARD _PROTOTYPE( int w_reset, (void) );
FORWARD _PROTOTYPE( void w_intr_wait, (void) );
FORWARD _PROTOTYPE( int at_intr_wait, (void) );
FORWARD _PROTOTYPE( int w_waitfor, (int mask, int value) );
FORWARD _PROTOTYPE( void w_geometry, (struct partition *entry) );

/* 进入这个驱动程序 */
PRIVATE struct driver w_dtab = {    /* 是不是 等待_驱动程序表 ？ 等待_驱动程序标签 ？ */
    w_name,      /* current device’s name 现在的设备名称 */
    w_do_open,   /* open or mount request, initialize device 打开或者挂载请求，初始化设备 */
    w_do_close,  /* release device 释放设备 */
    do_diocntl,  /* get or set a partition’s geometry 获取或者设置一个分区的几何 */
    w_prepare,   /* prepare for I/O on a given minor device 在给定的次要设备上准备 I/O */
    w_transfer,  /* do the I/O 做 I/O */
    nop_cleanup, /* nothing to clean up 没什么可以清理的 */
    w_geometry,  /* tell the geometry of the disk 告诉磁盘的几何 */
    nop_signal,  /* no cleanup needed on shutdown 关机时不需要清理 */
    nop_alarm,   /* ignore leftover alarms 忽略剩余的报警 */
    nop_cancel,  /* ignore CANCELs 忽略取消 */
    nop_select,  /* ignore selects 忽略选择 */
    w_other,     /* catch-all for unrecognized commands and ioctls 全部用于无法识别的命令和 I/O 控制s */
    w_hw_int     /* leftover hardware interrupts 剩余硬件中断 */
};

//  1.at_winchester_task  先进技术_温彻斯特_任务
//  2.init_params           初始化_参数
//  3.init_drive            初始化_驱动
//  4.init_params_pci       初始化_参数_Peripheral Component Interconnect(外设部件互连标准)
//  5.w_do_open           温彻斯特_做_打开
//  6.w_prepare           温彻斯特_准备
//  7.w_identify          温彻斯特_标识
//  8.w_name              温彻斯特_姓名
//  9.w_io_test           温彻斯特_输入输出_测试
// 10.w_specify           温彻斯特_详述
// 11.do_transfer               做_传输
// 12.w_transfer          温彻斯特_传输
// 13.com_out                 命令_输出
// 14.w_need_reset        温彻斯特_需要_重新设置
// 15.w_do_close          温彻斯特_做_关闭
// 16.com_simple              命令_简单
// 17.w_timeout           温彻斯特_超时
// 18.w_reset             温彻斯特_重新设置
// 19.w_intr_wait         温彻斯特_中断_等待
// 20.at_intr_wait        先进技术_中断_等待
// 21.w_waitfor           温彻斯特_等待为了
// 22.w_geometry          温彻斯特_几何
// 23.w_other             温彻斯特_其他
// 24.w_hw_int            温彻斯特_硬件_整型
// 25.ack_irqs                确定_中断  